/*
 * Created on Nov 11, 2003
 */
package com.unash.server;

/**
 * @author Ashwini Gokhale
 */
import com.unash.util.Consts;

public class Channel implements Consts{
	final Object[] elements;  
	private int   putPtr    = ZERO;
	private int   takePtr   = ZERO;   
	private int   usedSlots = ZERO;
	
	public Channel(int capacity) throws IllegalArgumentException{
		if(capacity <= ZERO)
			throw new IllegalArgumentException();
		elements = new Object[capacity];
	}//Channel
	
	/**
	 * This function adds a new element in the channel.
	 * If the channel is full then this function will not return until
	 * an element is taken out of the channel making space to add the element.
	 * It sends notify if the channel was previously empty.
	 * @param x Runnable Object
	 * @return void
	 */
	public synchronized void put(Object x) throws InterruptedException{
		while(usedSlots == elements.length) //all slots are in use
			wait();
		elements[putPtr] = x;
		putPtr = (putPtr + ONE) % elements.length; //cyclcally inc
		
		if(usedSlots++ == ZERO) //Signal if was empty
			notifyAll();
	}//put
	
	
	/**
	 *This function removes the element from the channel. 
	 * If the channel is empty then this function will not return until 
	 * an element is added 
	 **/
	public synchronized Object take() throws InterruptedException{
		while(usedSlots == ZERO)	//wait until not empty
			wait();
		
		Object x = elements[takePtr];
		elements[takePtr] = null;
		takePtr = (takePtr + ONE) % elements.length;
		
		if(usedSlots-- == elements.length)		//signal if was full
			notifyAll();
		return x;
	}//take

}//Channel